package com.lp.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.lp.bo.UserInfoBO;
import com.lp.cache.CacheName;
import com.lp.cache.ProCacheUtil;
import com.lp.cfg.ProConfig;
import com.lp.common.Code;
import com.lp.service.base.FileInfoService;
import com.lp.util.LogUtil;
import com.lp.util.ObjectUtil;
import com.lp.util.ResultMapUtils;

import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;

@Controller
public class WxMpController extends BaseController {
	
	@Resource(name = "wxMpService")
	private WxMpServiceImpl wxMpService;
	
	@Resource(name = "wxMpMessageRouter")
	private WxMpMessageRouter wxMpMessageRouter;
	
	@Autowired
	private WxMpInMemoryConfigStorage wxMpConfigStorage;
	

	/**
	 * 微信消息 和事件推送
	 * 
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @param req
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(method = RequestMethod.GET, value = "weixin/mp/msg")
	public void verifyMsg(@RequestParam(value = "signature", required = false) String signature,
			@RequestParam(value = "timestamp", required = false) String timestamp,
			@RequestParam(value = "nonce", required = false) String nonce,
			@RequestParam(value = "echostr", required = false) String echostr, HttpServletRequest req,
			HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		out.write(echostr);
		out.flush();
	}

	/**
	 * 微信消息 和事件推送
	 * 
	 * @param req
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(method = RequestMethod.POST, value = "weixin/mp/msg")
	public void rcvMsg(HttpServletRequest req, HttpServletResponse response) throws Exception {
		WxMpXmlMessage msg = WxMpXmlMessage.fromXml(req.getInputStream());
		// 事件
		if (WxConsts.XML_MSG_EVENT.equals(msg.getMsgType())) {
			// subscribe(订阅) 、 unsubscribe(取消订阅)
			if ("subscribe".equals(msg.getEvent())) {
				// 给用户发送含有绑定url的消息通知
				String user_open_id = msg.getFromUserName();

				WxMpCustomMessage ms = new WxMpCustomMessage();
				ms.setToUser(user_open_id);
				ms.setMsgType("text");
				ms.setContent("欢迎关注"+ ProConfig.PROJECT_NAME +"公众号服务平台！");	
				wxMpService.customMessageSend(ms);
				
				// 发送图文消息

			} else if ("unsubscribe".equals(msg.getEvent())) {
				// 取消订阅
			}
		}else if(WxConsts.XML_MSG_TEXT.equals(msg.getMsgType()) ){
			// 文字消息
			
		}else if(WxConsts.XML_MSG_IMAGE.equals(msg.getMsgType()) ){
			// 图片消息
			
		}
	}

	/**
	 * 创建微信菜单
	 * 
	 * @param req
	 * @param response
	 * @throws IOException
	 * @throws WxErrorException
	 */
	@RequestMapping(method = RequestMethod.GET, value = "weixin/mp/menu/create")
	public void menuCreate(HttpServletRequest req, HttpServletResponse response) throws IOException, WxErrorException {
		PrintWriter out = response.getWriter();
		response.setCharacterEncoding("UTF-8");
		createMenu(out);
		out.write("menu create OK!");
		out.flush();
	}

	/**
	 * 微信网页授权回调接口
	 * 
	 * @param req
	 * @param response
	 * @param state
	 * @param code
	 * @throws IOException
	 * @throws WxErrorException
	 */
	@RequestMapping(method = RequestMethod.GET, value = "oauth2/authorize/weixin/mp")
	public String authCallback(HttpServletRequest req, HttpServletResponse response,
			@RequestParam(required = false) String state, @RequestParam(required = false) String code)
					throws IOException, WxErrorException {
		if (!StringUtils.isEmpty(code)) {
			// 通过code换取网页授权access_token
			WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
			// ---
			String openid = wxMpOAuth2AccessToken.getOpenId();
			// 设置到session中
			req.getSession().setAttribute("open_id", openid);
			
			if(state.contains("cbind")){
				WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, "zh_CN");
				// 联系人信息绑定
				UserInfoBO userx = new UserInfoBO() ;
				userx.setWx_open_id(openid);
				if( wxMpUser.getHeadImgUrl().length() > 190 ){
					userx.setWx_img_url(wxMpUser.getHeadImgUrl());						
				}else{
					// 设置默认图片
					userx.setWx_img_url(ProConfig.LOCAL_DOMAIN +"/image/oss/iot/default.jpg" );	
				}
				req.getSession().setAttribute("user", userx);
				// 这个session 时间设置的短一点
				req.getSession().setMaxInactiveInterval(30);
				return "redirect:" + state.replace("*", "&");
			}
			
			UserInfoBO user = ProCacheUtil.getCache(CacheName.USERINFO_OPENID, openid);
			
			if( ObjectUtil.isEmpty(user) ){
				// 获取用户更多的信息，snap_userinfo 授权
				WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, "zh_CN");	
				
				if( state.contains("bind") ){
					// 账户绑定,将微信或者url
					if(wxMpUser.getHeadImgUrl().length() < 180){
						req.getSession().setAttribute("wximg", wxMpUser.getHeadImgUrl());						
					}
					req.getSession().setAttribute("nickname", wxMpUser.getNickname());
					// 跳转到绑定页面
					return "redirect:/service/wiot/bind" ;
					
				}
			}
			// 账户已存在，则不做处理
			req.getSession().setAttribute("user", user);
		}
		return "redirect:" + state.replace("*", "&");
	}

	/**
	 * 创建菜单
	 * 
	 * @throws WxErrorException
	 * @throws UnsupportedEncodingException
	 *             test:
	 *             http://chen.sub.testlg.com/lpro/service/weixin/mp/menu/create
	 */
	
	public String createMenu(PrintWriter out) throws WxErrorException, UnsupportedEncodingException {
		String ret_msg = null;
		// 初始化菜单
		WxMenu wxMenu = new WxMenu();
		// 微信一级菜单列表
		List<WxMenuButton> menuList = new ArrayList<WxMenuButton>();
		
		String url = ProConfig.LOCAL_DOMAIN ;
		
		generateWeixinMenu(menuList, Arrays.asList("实时监控", url+ "/service/wiot/scene"), null);
		
		generateWeixinMenu(menuList, Arrays.asList("报警管理", url+ "/service/wiot/alarm"), null);
		
		generateWeixinMenu(menuList, Arrays.asList("个人信息") , 
				Arrays.asList( 
						Arrays.asList("项目信息",url+ "/service/wiot/mscene"),
						Arrays.asList("设备配网",url+ "/service/wiot/deviceConfigwifi")
					));
		
		wxMenu.setButtons(menuList);
		wxMpService.menuCreate(wxMenu);
		return ret_msg;
	}

	/**
	 * 工具类
	 * @param menuList
	 * @param parent
	 * @param sub
	 */
	private void generateWeixinMenu(List<WxMenuButton> menuList,List<String> parent,List<List<String>> sub ){
		WxMenuButton parentMenu = new WxMenuButton();
		if(parent.size() >1){
			parentMenu.setName(parent.get(0));
			parentMenu.setType("view");
			parentMenu.setUrl(parent.get(1));
		}else{
			parentMenu.setName(parent.get(0));
			parentMenu.setType("view");
			
			List<WxMenuButton> secordBtns = new ArrayList<WxMenuButton>();
			
			for(int i=0; i< sub.size();i++){
				WxMenuButton askBtn = new WxMenuButton();
				askBtn.setName(sub.get(i).get(0));
				askBtn.setType("view");
				askBtn.setUrl(sub.get(i).get(1));
				secordBtns.add(askBtn);
			}
			parentMenu.setSubButtons(secordBtns);
		}
		menuList.add(parentMenu);
	}
	
	@Autowired
	private FileInfoService fileInfoService ;
	
	/**
	 * 将提交到微信文件下载并提交到服务器
	 * 
	 * @param req
	 * @param resp
	 * @return
	 */
	@RequestMapping(method = RequestMethod.GET, value = "/wx/media/{media_id}")
	public ModelAndView getWxMediaInfo(HttpServletRequest req, HttpServletResponse resp,
			@RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey, @PathVariable String media_id) {
		// media_id为附件上传到微信平台的id
		Map<String, Object> resultMap = getResultMap();
		try {
			UserInfoBO user = getUserInfoByUserKey(userKey) ;
			if(ObjectUtil.isNotEmpty(user)){
				resultMap = fileInfoService.downFileImgFromWxServer(wxMpConfigStorage.getAccessToken(), media_id, user.getId());
			}else{
				putStatusCode(resultMap, Code.ResponseCode.SystemCode.NO_AUTHORIZATION);
			}
		} catch (Exception e) {
			putStatusCode(resultMap, Code.ResponseCode.SystemCode.ERROR);
			LogUtil.errorLog(e.getMessage());
		}
		return getModelAndView(resp, resultMap);
	}
	
	
	/**
	 * 发送临时图片消息
	 * 
	 * @param open_id
	 * @param content
	 */
	public void sendWxMpCustomTempImageMessage(String wx_open_id, String imagePath, String title) {
		InputStream inputStream = null;
		try {
			 File imageFile = new File(imagePath);
			 inputStream = new FileInputStream(imageFile);
			 byte b[] = new byte[(int) imageFile.length()]; // 创建合适文件大小的数组
			 inputStream.read(b); // 读取文件中的内容到b[]数组

			// 上传临时图片
			WxMediaUploadResult wxMediaUploadResult = wxMpService.mediaUpload(WxConsts.CUSTOM_MSG_IMAGE, "jpg",
					inputStream);

			// 发送图片消息
			WxMpCustomMessage wm = new WxMpCustomMessage();
			wm.setToUser(wx_open_id);
			wm.setMsgType(WxConsts.CUSTOM_MSG_IMAGE);
			// wm.setToUser("from " + wx_open_id);
			wm.setMediaId(wxMediaUploadResult.getMediaId());

			wxMpService.customMessageSend(wm);

		} catch (Exception e) {
			LogUtil.errorLog(e.getMessage());
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}
